package com.common.aspect;

import com.common.annotation.LogAnnotation;
import com.common.service.OperationLogService;
import com.common.util.ConstantDefine;
import com.common.util.ShiroUtil;
import com.common.vo.OperationLogVO;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

@Aspect
public class LogAspect {

    @Autowired
    private OperationLogService operationLogService;

    /**
     * 添加业务逻辑方法切入点
     */
//    @Pointcut("execution(* com.common.controller.*.*(..))")
    @Pointcut("@annotation(com.common.annotation.LogAnnotation)")
    public void insertCell() {

    }


    /**
     * 添加操作日志(后置通知)
     *
     * @param joinPoint
     * @param object
     */
    @AfterReturning(value = "insertCell()", returning = "object")
    public void insertLog(JoinPoint joinPoint, Object object) throws Throwable {
        System.out.println("拦截后进来！");
        OperationLogVO operationLogVO = new OperationLogVO();
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //获取ip、接口名、操作人等信息
        getMsg(operationLogVO,request,joinPoint);
        operationLogVO.setResult("1");
        int insert = operationLogService.insert(operationLogVO);
        if (insert > 0){
            System.out.println("插入操作记录成功");
        }else{
            System.out.println("插入操作记录失败");
        }
    }

    /**
     * 添加操作日志(异常通知)
     *
     * @param
     * @param
     */
    @AfterThrowing(value = "insertCell()")
    public void exceptionLog(JoinPoint joinPoint) throws Throwable {
        System.out.println("拦截后进来！");
        OperationLogVO operationLogVO = new OperationLogVO();
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //获取ip、接口名、操作人等信息
        getMsg(operationLogVO,request,joinPoint);
        operationLogVO.setResult("0");
        int insert = operationLogService.insert(operationLogVO);
        if (insert > 0){
            System.out.println("插入操作记录成功");
        }else{
            System.out.println("插入操作记录失败");
        }
    }

    /**
     * 获取注解内容
     *
     * @param joinPoint
     * @return
     * @throws Exception
     */
    public LogAnnotation getMthodRemark(JoinPoint joinPoint) throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] method = targetClass.getMethods();
        LogAnnotation logAnnotation = null;
        for (Method m : method) {
            if (m.getName().equals(methodName)) {
                Class[] tmpCs = m.getParameterTypes();
                if (tmpCs.length == arguments.length) {
                    logAnnotation = m.getAnnotation(LogAnnotation.class);
                    if (logAnnotation != null) {
                        return logAnnotation;
                    }
                    break;
                }
            }
        }
        return logAnnotation;
    }

    public String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    private void getMsg(OperationLogVO operationLogVO, HttpServletRequest request, JoinPoint joinPoint) {
        // 获取接口名称
        String content = request.getRequestURI();
        operationLogVO.setContent(content);
        System.out.println(content);
        // 获取参数
        Object[] args = joinPoint.getArgs();
        System.out.println(args);
        // 获取方法名
        String methodName = joinPoint.getSignature().getName();
        // 获取指定注解属性
        LogAnnotation logAnnotation = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(LogAnnotation.class);
        // 操作类型
        String type = logAnnotation.bizID();
        operationLogVO.setType(type);
        // 功能描述
        String description = logAnnotation.description();
        operationLogVO.setDescription(description);
        System.out.println(type);
        System.out.println(description);
        //获取用户的登录名称作为操作人员以及记录下请求的ip地址
        Object creator = ShiroUtil.getSessionByKey(ConstantDefine.ACCOUNT_CODE_SESSION);
        System.out.println(creator);
        if(creator != null){
            operationLogVO.setCreatedBy(creator.toString());
            String ipAddress = getIpAddress(request);
            System.out.println(ipAddress);
            operationLogVO.setIp(ipAddress);
        }
    }

}
